package com.su.lightthings.viewmodel

import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.util.Log
import androidx.lifecycle.MutableLiveData
import com.jieli.jl_bt_ota.constant.StateCode
import com.jieli.jl_bt_ota.util.BluetoothUtil
import com.kunminx.architecture.domain.message.MutableResult
import com.su.lightthings.base.BaseApplication
import com.su.lightthings.bean.ReceiveDataBean
import com.su.lightthings.ble.model.BleScanInfo
import com.su.lightthings.bluetooth.BtUtil
import com.su.lightthings.bluetooth.OnBTEventCallback
import com.su.lightthings.bluetooth.ProtocolDataUtil
import com.su.lightthings.entity.ConnectedDeviceEntity
//import com.su.lightthings.entity.ConnectedDeviceEntity_
import com.su.lightthings.mode.DeviceConnection
import com.su.lightthings.mode.ScanDevice
import com.su.lightthings.mode.ScanResult
import com.su.lightthings.net.WeatherUtil
import com.su.lightthings.service.DataAnalysis
import com.su.lightthings.utils.AppUtil
import com.su.lightthings.utils.AudioUtil
import com.su.lightthings.utils.CallUtil
import com.su.lightthings.utils.CameraUtil
import com.su.lightthings.utils.Cons
import com.su.lightthings.utils.OtaConstant
import com.su.lightthings.utils.RingUtil
import com.su.lightthings.utils.SpUtil
//import io.objectbox.query.QueryBuilder
import java.util.UUID


/**
 * @author zqjasonZhong
 * @since 2022/9/8
 * @email zhongzhuocheng@zh-jieli.com
 * @desc 连接设备逻辑实现
 */
class ConnectViewModel : BluetoothViewModel() {

    val bluetoothStateMLD = MutableLiveData<Boolean>()
    val scanResultMLD = MutableLiveData<ScanResult>()
    val deviceConnectionMLD = MutableLiveData<DeviceConnection>()
    val historyConnectListMLD = MutableLiveData<MutableList<ConnectedDeviceEntity>>()
    var connectingDeviceAddress: String = ""

    //    val rawData = MutableLiveData(byteArrayOf())
    var bleData: MutableResult<ReceiveDataBean> = MutableResult<ReceiveDataBean>()

    var tempConnectedDevice: BluetoothDevice? = null

    companion object {
        private const val TAG = "ConnectViewModel"

            val INSTANCE: ConnectViewModel by lazy {
            ConnectViewModel()
        }
    }


    private val btEventCallback = object : OnBTEventCallback() {

        override fun onAdapterChange(bEnabled: Boolean) {
            bluetoothStateMLD.postValue(bEnabled)
        }

        override fun onDiscoveryChange(bStart: Boolean, scanType: Int) {
            val result = if (bStart) {
                ScanResult(ScanResult.SCAN_STATUS_SCANNING)
            } else {
                ScanResult(ScanResult.SCAN_STATUS_IDLE)
            }
            scanResultMLD.value = result
        }

        override fun onDiscovery(device: BluetoothDevice?, bleScanMessage: BleScanInfo?) {
            val result = ScanResult(ScanResult.SCAN_STATUS_FOUND_DEV,
                device?.let {
                    val data = bleScanMessage?.rawData ?: ByteArray(0)
                    ScanDevice(it, bleScanMessage?.rssi ?: 0, data)
                })
            scanResultMLD.value = result
        }

        override fun onDeviceConnection(device: BluetoothDevice?, way: Int, status: Int) {
            val newStatus = AppUtil.changeConnectStatus(status)
            deviceConnectionMLD.value =
                DeviceConnection(device, newStatus)
            Log.d(TAG, "newStatus: $newStatus")
            if (newStatus == StateCode.CONNECTION_CONNECTED || newStatus == StateCode.CONNECTION_OK) {
                tempConnectedDevice = device
                //判断数据库中该设备是否已经绑定
                val has = device?.let { hasDeviceInBox(it) };
                if (has == true) {
                    //已经绑定：发送状态：BIND
                    Log.d(TAG, "已经绑定：发送状态 > BIND")
                    deviceConnectionMLD.value =
                        DeviceConnection(device, Cons.BleConnectState.BIND)
                    SpUtil.putData(Cons.SP.SP_DEVICE_ADDRESS, device.address ?: "")
                } else {
                    //未绑定：发送绑定协议
                    val data = BtUtil.makeWriteData(functionId = Cons.BondFunctionId.BIND)
                    Log.d(TAG, "未绑定：发送绑定协议 > $data")
                    BleViewModel.INSTANCE.write(data);
                }
                //如果当前状态为OTA状态，则不保存该设备。因为同一个设备在OTA时MAC地址会变。
//                if (SpUtil.getData(
//                        Cons.SP.SP_IS_OTA,
//                        Cons.OTA.OTA_NONE
//                    ) as Int == Cons.OTA.OTA_NONE
//                ) {
//                    SpUtil.putData(Cons.SP.SP_DEVICE_ADDRESS, device?.address ?: "")
//                }
            } else {
                tempConnectedDevice = null
            }
        }

        override fun onReceiveData(
            device: BluetoothDevice?,
            way: Int,
            uuid: UUID?,
            data: ByteArray?
        ) {
            super.onReceiveData(device, way, uuid, data)
            Log.d(TAG, "onReceiveData  uuid >>  : $uuid")
            when (uuid) {
                Cons.BleUUID.BLE_UUID_NOTIFICATION -> {
                    if (data != null) {
                        val packageData = DataAnalysis.packageData(data)
                        if (packageData != null) {
                            val receiveData = DataAnalysis.analysisReceiveData(data)
                            bleData.value = receiveData
                            doTask(device?.address, receiveData)
                        }
                    }
                }
            }
        }
    }

    init {
        bluetoothHelper.registerCallback(btEventCallback)
    }

    fun isScanning(): Boolean = bluetoothHelper.isScanning()

    fun startScan() {
        if (!BluetoothUtil.isBluetoothEnable()) {
            AppUtil.enableBluetooth(BaseApplication.instance)
            return
        }
        bluetoothHelper.startScan(OtaConstant.SCAN_TIMEOUT)
    }

    fun stopScan() {
        bluetoothHelper.stopScan()
    }

    fun connectBtDevice(device: BluetoothDevice?) {
        if (null == device) return
        bluetoothHelper.connectDevice(device)
    }

    fun connectBtDevice(address: String?) {
        if (null == address || "" == address) return
        bluetoothHelper.connectDevice(address)
    }

    fun disconnectBtDevice(device: BluetoothDevice?) {
        if (null == device) return
        bluetoothHelper.disconnectDevice(device)
    }

    fun disconnectBtDevice() {
        bluetoothHelper.disconnectDevice(getConnectedDevice())
    }

    fun getHistoryDevice() {
//        val deviceBox = ObjectBox.boxStore.boxFor(ConnectedDeviceEntity::class.java)
//        val devices = deviceBox.all
//        devices.sortByDescending { device -> device.lastConnectTimeStamp }
//        Log.d(TAG, "getHistoryDevice: $devices")
//        historyConnectListMLD.postValue(devices)
    }


    fun destroy() {
        stopScan()
        bluetoothHelper.unregisterCallback(btEventCallback)
    }

    private fun doTask(address: String?, task: ReceiveDataBean) {
        Log.d(TAG, "设备发来的请求任务: $task")
        when (task.functionId) {
            //申请绑定
            Cons.BondFunctionId.BIND -> {
//              判断用户是否同意绑定
                val bind = task.dataLongMap["bind"]
                Log.d(TAG, "是否同意绑定:$bind")
                if (bind == 0L) {
//                如果同意：更新状态为 BINDED
                    deviceConnectionMLD.value =
                        DeviceConnection(tempConnectedDevice, Cons.BleConnectState.BIND)
                    SpUtil.putData(Cons.SP.SP_DEVICE_ADDRESS, address ?: "")
                } else {
//                如果不同意：断开设备连接
                    disconnectBtDevice(tempConnectedDevice)
                }
            }
            //申请配对
            Cons.BondFunctionId.PAIR -> {
                BtUtil.bondDevice(
                    BluetoothAdapter.getDefaultAdapter(),
                    getConnectedDevice()?.address ?: ""
                )
            }

            //时间更新
            Cons.PushFunctionId.TIME_UPDATE -> {
                val timestamp = System.currentTimeMillis()
                if (task.dataLength == 0) {
                    BleViewModel.INSTANCE.write(
                        BtUtil.makeWriteData(
                            functionId = Cons.PushFunctionId.TIME_UPDATE,
                            data = ProtocolDataUtil.updateTime(timestamp)
                        )
                    )
                }
            }

            //音量调整
            Cons.PushFunctionId.MUSIC_CONTROL -> {
                val event = task.dataLongMap["volume"]
                if (event != null) {
                    AudioUtil.controlVolume(event.toInt())
                }
            }

            //相机控制
            Cons.SettingFunctionId.CAMERA_CONTROL -> {
                val event = task.dataLongMap["switch"]
                if (event != null) {
                    CameraUtil.control(event.toInt())
                }
            }

            //通话控制
            Cons.SettingFunctionId.PHONE_CONTROL -> {
                val event = task.dataLongMap["switch"]
                if (event != null) {
                    CallUtil.control(event.toInt())
                }
            }

            Cons.SettingFunctionId.FIND_PHONE -> {
                val event = task.dataLongMap["type"]?.toInt() ?: -1
                RingUtil.control(event)
            }

            //天气推送
            Cons.PushFunctionId.WEATHER -> {
                if (task.dataLength == 0) {
                    WeatherUtil.sendCurrentWeatherToWatch()
                }
            }
            //未来天气推送
            Cons.PushFunctionId.FUTURE_WEATHER -> {
                if (task.dataLength == 0) {
                    WeatherUtil.sendFutureWeatherToWatch()
                }
            }
        }
    }

    /**
     * 查找数据库中 是否存在该设备
     */
    private fun hasDeviceInBox(device: BluetoothDevice): Boolean {
//        val deviceBox = ObjectBox.boxStore.boxFor(ConnectedDeviceEntity::class.java)
//        //要查找的设备
//        val address = device.address;
//        //找到数据库中对应的设备
//        val result = deviceBox.query().equal(
//            ConnectedDeviceEntity_.address,
//            address,
//            QueryBuilder.StringOrder.CASE_INSENSITIVE
//        ).build().findFirst()
//        Log.d(
//            TAG,
//            "查找数据库中是否存在该设备: ${result != null} >> ${result?.name} >> ${result?.address}"
//        )
//        return result != null
        return false
    }

}